package com.ktgj.common.core.utils.helper;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.ktgj.common.core.utils.xml.XmlClass;
import com.ktgj.common.core.utils.xml.XmlPropertyData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ReflectHelper
{
	private final static Logger LOGGER = LoggerFactory.getLogger(ReflectHelper.class);

	public static Field getField(Class<?> clazz, String fieldname)
	{
		List<Field> fields = ReflectHelper.getFields(clazz);
		if (fields == null || fields.size() == 0) return null;

		for (Field field : fields)
		{
			if (field.getName().equalsIgnoreCase(fieldname))
			{
				return field;
			}
		}

		return null;
	}

	public static List<Field> getFields(Class<?> clazz)
	{
		List<Field> fields = new ArrayList<>();
		while (clazz != null)
		{
			fields.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
			clazz = clazz.getSuperclass();
		}

		return fields;
	}

	public static <T> XmlClass getXmlClass(Class<?> clazz)
	{
		return clazz.getDeclaredAnnotation(XmlClass.class);
	}

	public static List<XmlPropertyData> getXmlProperties(Class<?> clazz)
	{
		List<XmlPropertyData> result = new ArrayList<XmlPropertyData>();

		for (Field field : ReflectHelper.getFields(clazz))
		{
			XmlPropertyData data = field.getDeclaredAnnotation(XmlPropertyData.class);

			if (data != null) result.add(data);
		}

		return result;
	}

	@SuppressWarnings("unused")
	public static <T> Object getValue(T t, String name)
	{
		Class<?> clazz = t.getClass();
		Field pInfo;
		boolean access = false;
		try
		{
			pInfo = ReflectHelper.getField(clazz, name);
			access = pInfo.isAccessible();
		}
		catch (Exception e)
		{
			LOGGER.error(e.getMessage());
			return null;
		}

		if (pInfo != null)
		{
			try
			{
				if (!access)
				{
					pInfo.setAccessible(true);
				}
				return pInfo.get(t);
			}
			catch (IllegalArgumentException e)
			{
				LOGGER.error(e.getMessage());
				return null;
			}
			catch (IllegalAccessException e)
			{
				LOGGER.error(e.getMessage());
				return null;
			}
			finally
			{
				if (!access && pInfo != null)
				{
					pInfo.setAccessible(false);
				}
			}
		}

		return null;
	}

	public static <T> boolean setValue(T t, String name, Object value)
	{
		Class<?> clazz = t.getClass();
		Field pInfo;
		boolean access = false;
		try
		{
			pInfo = ReflectHelper.getField(clazz, name);
			access = pInfo.isAccessible();
		}
		catch (Exception e)
		{
			LOGGER.error(e.getMessage());
			return false;
		}

		try
		{
			if (!access)
			{
				pInfo.setAccessible(true);
			}

			Object val = SimpleConverter.convert(value, pInfo.getType());
			pInfo.set(t, val);
			return true;
		}
		catch (IllegalArgumentException e)
		{
			LOGGER.error(e.getMessage());
			return false;
		}
		catch (IllegalAccessException e)
		{
			LOGGER.error(e.getMessage());
			return false;
		}
		finally
		{
			if (!access)
			{
				pInfo.setAccessible(false);
			}
		}
	}

}
